JAVA IO¶
BIO¶
同步阻塞模式。 线程发起IO请求后,一直阻塞IO,直到缓冲区数据就绪后,再进入下一步操作。
服务端会调用 accept() 方法等待接收客户端的连接的方式监听请求,请求一旦接收到一个连接请求,就可以建立通信套接字在这个通信套接字上进行读写操作,此时不能再接收其他客户端连接请求,只能等待同当前连接的客户端的操作执行完成, 不过可以通过多线程来支持多个客户端的连接。
如果要让 BIO 通信模型 能够同时处理多个客户端请求,就必须使用多线程(socket.accept()、socket.read()、socket.write() 涉及的三个主要函数都是同步阻塞的)。
NIO¶
同步非阻塞。同步指的是必须等待IO缓冲区内的数据就绪;非阻塞指,用户线程不原地等待IO缓冲区,可以先做一些其他操作,但是要定时轮询检查IO缓冲区数据是否就绪。
- 面向缓冲的,基于通道的I/O操作方法。
- 通过零拷贝的buffer取得数据
- 通过 channel 在selector(多路复用器)上进行注册
- 服务端不断轮询 channe l来获取客户端的信息
缓冲区 :IO 面向流(Stream oriented),而 NIO 面向缓冲区(Buffer oriented)¶
任何时候访问NIO中的数据,都是通过缓冲区进行操作。
而 IO 面向流的,数据直接写入或者将数据直接读到 Stream 对象中。
选择器¶
选择器用于使用单个线程处理多个通道,无需切换线程。
读写方式¶
NIO中的所有IO都是从 Channel(通道) 开始的。
- 从通道进行数据读取 :创建一个缓冲区,然后请求通道读取数据。
- 从通道进行数据写入 :创建一个缓冲区,填充数据,并要求通道写入数据。
Buffer¶
属性¶
| 属性 | 说明 |
|---|---|
| capacity 容量 | Buffer 所能容纳数据元素的最大数量,也就是底层数组的容量值。在创建时被指定,不可更改。 |
| position 位置 | 下一个被读或被写的位置 |
| limit 上界 | 可供读写的最大位置,用于限制 position,position < limit |
| mark 标记 | 位置标记,用于记录某一次的读写位置,可以通过 reset 重新回到这个位置 |
读写操作¶
- 每当写入了一个单位的数据后, position就会递增1
- 调用了 filp 方法将 Buffer 从写模式转换到读模式时, position 的值会自动被设置为0
- 每当读取一个单位的数据, position 的值递增1
读写操作都会修改 position 的值,每次读写的位置是当前 position 的下一个位置。通过修改 position,我们可以读取指定位置的数据。
读取刚写完的操作时,需要同时修改 position 和 limit。函数 flip 可以合二为一;
AIO¶
异步非阻塞。NIO中,仍需用户线程定时轮询IO缓冲区状态。AIO的异步非阻塞IO应该让内核系统完成轮询,等待通知。
字节流与字符流¶
1个字节(1 byte)= 2个字符
- 字节流操作的基本单元为字节;字符流操作的基本单元为Unicode码元。
- 字节流默认不使用缓冲区;字符流使用缓冲区。
- 字节流通常用于处理二进制数据,实际上它可以处理任意类型的数据,但它不支持直接写入或读取Unicode码元; 字符流通常处理文本数据,它支持写入及读取Unicode码元。